Repository: nodejs/node
Pull request: tools: add inspector_protocol updater

Rolls `deps/inspector_protocol` with a GHA workflow.

Changed files:
filename: .github/workflows/tools.yml
patch: @@ -25,6 +25,7 @@ on:
           - gyp-next
           - histogram
           - icu
+          - inspector_protocol
           - libuv
           - llhttp
           - minimatch
@@ -149,6 +150,14 @@ jobs:
               cat temp-output
               tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true
               rm temp-output
+          - id: inspector_protocol
+            subsystem: deps
+            label: dependencies, inspector
+            run: |
+              ./tools/dep_updaters/update-inspector-protocol.sh > temp-output
+              cat temp-output
+              tail -n1 temp-output | grep "NEW_VERSION=" >> "$GITHUB_ENV" || true
+              rm temp-output
           - id: libuv
             subsystem: deps
             label: dependencies
@@ -276,7 +285,9 @@ jobs:
         with:
           persist-credentials: false
       - name: Set up Python ${{ env.PYTHON_VERSION }}
-        if: matrix.id == 'icu' && (github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id)
+        if: |
+          (matrix.id == 'icu' || matrix.id == 'inspector_protocol') &&
+          (github.event_name == 'schedule' || inputs.id == 'all' || inputs.id == matrix.id)
         uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c  # v6.0.0
         with:
           python-version: ${{ env.PYTHON_VERSION }}

filename: tools/dep_updaters/update-inspector-protocol.sh
patch: @@ -0,0 +1,45 @@
+#!/bin/sh
+set -e
+# Shell script to update inspector_protocol in the source tree to the version same with V8's.
+
+BASE_DIR=$(cd "$(dirname "$0")/../.." && pwd)
+DEPS_DIR="$BASE_DIR/deps"
+
+# shellcheck disable=SC1091
+. "$BASE_DIR/tools/dep_updaters/utils.sh"
+
+echo "Making temporary workspace..."
+
+WORKSPACE=$(mktemp -d 2> /dev/null || mktemp -d -t 'tmp')
+
+cd "$WORKSPACE"
+
+git clone https://chromium.googlesource.com/deps/inspector_protocol.git
+
+INSPECTOR_PROTOCOL_DIR="$WORKSPACE/inspector_protocol"
+
+echo "Comparing latest upstream with current revision"
+
+set +e
+python "$BASE_DIR/tools/inspector_protocol/roll.py" \
+  --ip_src_upstream "$INSPECTOR_PROTOCOL_DIR" \
+  --node_src_downstream "$BASE_DIR"
+STATUS="$?"
+set -e
+
+if [ "$STATUS" = "0" ]; then
+  echo "Skipped because inspector_protocol is on the latest version."
+  exit 0
+fi
+
+python "$BASE_DIR/tools/inspector_protocol/roll.py" \
+  --ip_src_upstream "$INSPECTOR_PROTOCOL_DIR" \
+  --node_src_downstream "$BASE_DIR" \
+  --force
+
+NEW_VERSION=$(grep "Revision:" "$DEPS_DIR/inspector_protocol/README.node" | sed -n "s/^Revision: \(\\w*\)/\1/p")
+
+# Update the version number on maintaining-dependencies.md
+# and print the new version as the last line of the script as we need
+# to add it to $GITHUB_ENV variable
+finalize_version_update "inspector_protocol" "$NEW_VERSION"

filename: tools/inspector_protocol/roll.py
patch: @@ -38,15 +38,13 @@ def RunCmd(cmd):
   return stdoutdata.decode('utf-8')
 
 
-def CheckRepoIsClean(path, suffix):
+def CheckRepoIsClean(path):
   os.chdir(path)  # As a side effect this also checks for existence of the dir.
   # If path isn't a git repo, this will throw and exception.
   # And if it is a git repo and 'git status' has anything interesting to say,
   # then it's not clean (uncommitted files etc.)
   if len(RunCmd(['git', 'status', '--porcelain'])) != 0:
     raise Exception('%s is not a clean git repo (run git status)' % path)
-  if not path.endswith(suffix):
-    raise Exception('%s does not end with /%s' % (path, suffix))
 
 
 def CheckRepoIsNotAtMainBranch(path):
@@ -85,6 +83,16 @@ def ReadV8IPRevision(node_src_path):
       return line[len(REVISION_LINE_PREFIX):]
   raise Exception('No V8 inspector protocol revision found')
 
+
+def ReadNodeIPRevision(node_src_path):
+  lines = open(os.path.join(node_src_path, 'deps/inspector_protocol/README.node')).readlines()
+  for line in lines:
+    line = line.strip()
+    if line.startswith(REVISION_LINE_PREFIX):
+      return line[len(REVISION_LINE_PREFIX):]
+  raise Exception('No Node inspector protocol revision found')
+
+
 def CheckoutRevision(path, revision):
   os.chdir(path)
   return RunCmd(['git', 'checkout', revision])
@@ -114,8 +122,8 @@ def main(argv):
   upstream = os.path.normpath(os.path.expanduser(args.ip_src_upstream))
   downstream = os.path.normpath(os.path.expanduser(
       args.node_src_downstream))
-  CheckRepoIsClean(upstream, '/src')
-  CheckRepoIsClean(downstream, '/node')
+  CheckRepoIsClean(upstream)
+  CheckRepoIsClean(downstream)
   CheckRepoIsInspectorProtocolCheckout(upstream)
   # Check that the destination Git repo isn't at the main branch - it's
   # generally a bad idea to check into the main branch, so we catch this
@@ -124,6 +132,10 @@ def main(argv):
 
   # Read V8's inspector_protocol revision
   v8_ip_revision = ReadV8IPRevision(downstream)
+  node_ip_revision = ReadNodeIPRevision(downstream)
+  if v8_ip_revision == node_ip_revision:
+    print('Node is already at V8\'s inspector_protocol revision %s - nothing to do.' % v8_ip_revision)
+    sys.exit(0)
   print('Checking out %s into %s ...' % (upstream, v8_ip_revision))
   CheckoutRevision(upstream, v8_ip_revision)