Commit 36e93be809 for openssl.org

commit 36e93be809b6c46b6596c6a318e086c7a6e59de3
Author: Georgy Karataev <georgyk@openssl.org>
Date:   Thu Jul 23 15:00:13 2026 +0200

    ci: centralize dispatch input validation

    Clarify the bot-only workflow inputs and validate any supplied tuple through
    a shared reusable workflow without interpolating input values into shell source.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

    Reviewed-by: Milan Broz <mbroz@openssl.org>
    Reviewed-by: Norbert Pocs <norbertp@openssl.org>
    MergeDate: Mon Jul 27 10:16:56 2026
    (Merged from https://github.com/openssl/openssl/pull/32053)

diff --git a/.github/workflows/ct-validation-daily.yml b/.github/workflows/ct-validation-daily.yml
index 36d1762b8b..61cd87ffa5 100644
--- a/.github/workflows/ct-validation-daily.yml
+++ b/.github/workflows/ct-validation-daily.yml
@@ -42,21 +42,19 @@ on:
   workflow_dispatch:
     inputs:
       pr:
-        description: 'PR number (leave empty for a bare manual run against the default branch)'
+        description: 'Internal: openssl-ci-bot PR number. Leave empty for a normal manual run.'
         required: false
         type: string
       head_sha:
-        description: 'Exact commit SHA to check out (required when pr is set)'
+        description: 'Internal: openssl-ci-bot commit SHA. Leave empty for a normal manual run.'
         required: false
         type: string
       check_run_id:
-        description: 'Check-run id to report completion back to (required when pr is set)'
+        description: 'Internal: openssl-ci-bot check-run ID. Leave empty for a normal manual run.'
         required: false
         type: string

-# Pinned run-name contract with images/openssl-ci-bot/main.py's format_run_name()/
-# parse_run_name() -- the completed-run handler parses check_run_id back out of
-# this exact format string, so keep both sides identical on any change.
+# Keep in sync with openssl-ci-bot's run-name parser.
 run-name: >-
   ${{ github.event.inputs.pr && format('ci-dispatch pr={0} head={1} check_run_id={2}', github.event.inputs.pr, github.event.inputs.head_sha, github.event.inputs.check_run_id) || github.workflow }}

@@ -69,17 +67,14 @@ permissions:

 jobs:
   validate-dispatch-inputs:
-    # Defense-in-depth on the untrusted-code boundary, in addition to the
-    # dispatching service's own validation: fail closed on malformed inputs
-    # before anything checks out a ref or runs.
-    if: github.repository == 'openssl/openssl' && github.event.inputs.pr != ''
-    runs-on: ubuntu-latest
-    steps:
-      - name: Validate pr / head_sha / check_run_id
-        run: |
-          [[ "${{ github.event.inputs.pr }}" =~ ^[0-9]+$ ]] || { echo "::error::pr must be numeric"; exit 1; }
-          [[ "${{ github.event.inputs.check_run_id }}" =~ ^[0-9]+$ ]] || { echo "::error::check_run_id must be numeric"; exit 1; }
-          [[ "${{ github.event.inputs.head_sha }}" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::head_sha must be a 40-character hex commit SHA"; exit 1; }
+    if: |
+      github.repository == 'openssl/openssl' &&
+      (inputs.pr != '' || inputs.head_sha != '' || inputs.check_run_id != '')
+    uses: ./.github/workflows/validate-dispatch-inputs.yml
+    with:
+      pr: ${{ inputs.pr }}
+      head_sha: ${{ inputs.head_sha }}
+      check_run_id: ${{ inputs.check_run_id }}

   ct-validation:
     needs: [validate-dispatch-inputs]
@@ -118,8 +113,6 @@ jobs:
       - uses: actions/checkout@v6
         with:
           persist-credentials: false
-          # Bare-manual/schedule triggers omit head_sha, in which case checkout
-          # falls back to its own default (github.sha) unchanged.
           ref: ${{ github.event.inputs.head_sha || github.sha }}

       - name: Install valgrind
diff --git a/.github/workflows/run-checker-daily.yml b/.github/workflows/run-checker-daily.yml
index 1c197bfa07..3263784f2b 100644
--- a/.github/workflows/run-checker-daily.yml
+++ b/.github/workflows/run-checker-daily.yml
@@ -14,21 +14,19 @@ on:
   workflow_dispatch:
     inputs:
       pr:
-        description: 'PR number (leave empty for a bare manual run against the default branch)'
+        description: 'Internal: openssl-ci-bot PR number. Leave empty for a normal manual run.'
         required: false
         type: string
       head_sha:
-        description: 'Exact commit SHA to check out (required when pr is set)'
+        description: 'Internal: openssl-ci-bot commit SHA. Leave empty for a normal manual run.'
         required: false
         type: string
       check_run_id:
-        description: 'Check-run id to report completion back to (required when pr is set)'
+        description: 'Internal: openssl-ci-bot check-run ID. Leave empty for a normal manual run.'
         required: false
         type: string

-# Pinned run-name contract with images/openssl-ci-bot/main.py's format_run_name()/
-# parse_run_name() -- the completed-run handler parses check_run_id back out of
-# this exact format string, so keep both sides identical on any change.
+# Keep in sync with openssl-ci-bot's run-name parser.
 run-name: >-
   ${{ github.event.inputs.pr && format('ci-dispatch pr={0} head={1} check_run_id={2}', github.event.inputs.pr, github.event.inputs.head_sha, github.event.inputs.check_run_id) || github.workflow }}

@@ -41,17 +39,14 @@ permissions:

 jobs:
   validate-dispatch-inputs:
-    # Defense-in-depth on the untrusted-code boundary, in addition to the
-    # dispatching service's own validation: fail closed on malformed inputs
-    # before anything checks out a ref or runs.
-    if: github.repository == 'openssl/openssl' && github.event.inputs.pr != ''
-    runs-on: ubuntu-latest
-    steps:
-      - name: Validate pr / head_sha / check_run_id
-        run: |
-          [[ "${{ github.event.inputs.pr }}" =~ ^[0-9]+$ ]] || { echo "::error::pr must be numeric"; exit 1; }
-          [[ "${{ github.event.inputs.check_run_id }}" =~ ^[0-9]+$ ]] || { echo "::error::check_run_id must be numeric"; exit 1; }
-          [[ "${{ github.event.inputs.head_sha }}" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::head_sha must be a 40-character hex commit SHA"; exit 1; }
+    if: |
+      github.repository == 'openssl/openssl' &&
+      (inputs.pr != '' || inputs.head_sha != '' || inputs.check_run_id != '')
+    uses: ./.github/workflows/validate-dispatch-inputs.yml
+    with:
+      pr: ${{ inputs.pr }}
+      head_sha: ${{ inputs.head_sha }}
+      check_run_id: ${{ inputs.check_run_id }}

   run-checker:
     needs: [validate-dispatch-inputs]
diff --git a/.github/workflows/valgrind-daily.yml b/.github/workflows/valgrind-daily.yml
index 1f35410954..d6c12705a7 100644
--- a/.github/workflows/valgrind-daily.yml
+++ b/.github/workflows/valgrind-daily.yml
@@ -14,21 +14,19 @@ on:
   workflow_dispatch:
     inputs:
       pr:
-        description: 'PR number (leave empty for a bare manual run against the default branch)'
+        description: 'Internal: openssl-ci-bot PR number. Leave empty for a normal manual run.'
         required: false
         type: string
       head_sha:
-        description: 'Exact commit SHA to check out (required when pr is set)'
+        description: 'Internal: openssl-ci-bot commit SHA. Leave empty for a normal manual run.'
         required: false
         type: string
       check_run_id:
-        description: 'Check-run id to report completion back to (required when pr is set)'
+        description: 'Internal: openssl-ci-bot check-run ID. Leave empty for a normal manual run.'
         required: false
         type: string

-# Pinned run-name contract with images/openssl-ci-bot/main.py's format_run_name()/
-# parse_run_name() -- the completed-run handler parses check_run_id back out of
-# this exact format string, so keep both sides identical on any change.
+# Keep in sync with openssl-ci-bot's run-name parser.
 run-name: >-
   ${{ github.event.inputs.pr && format('ci-dispatch pr={0} head={1} check_run_id={2}', github.event.inputs.pr, github.event.inputs.head_sha, github.event.inputs.check_run_id) || github.workflow }}

@@ -41,17 +39,14 @@ permissions:

 jobs:
     validate-dispatch-inputs:
-      # Defense-in-depth on the untrusted-code boundary, in addition to the
-      # dispatching service's own validation: fail closed on malformed inputs
-      # before anything checks out a ref or runs.
-      if: github.repository == 'openssl/openssl' && github.event.inputs.pr != ''
-      runs-on: ubuntu-latest
-      steps:
-        - name: Validate pr / head_sha / check_run_id
-          run: |
-            [[ "${{ github.event.inputs.pr }}" =~ ^[0-9]+$ ]] || { echo "::error::pr must be numeric"; exit 1; }
-            [[ "${{ github.event.inputs.check_run_id }}" =~ ^[0-9]+$ ]] || { echo "::error::check_run_id must be numeric"; exit 1; }
-            [[ "${{ github.event.inputs.head_sha }}" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::head_sha must be a 40-character hex commit SHA"; exit 1; }
+      if: |
+        github.repository == 'openssl/openssl' &&
+        (inputs.pr != '' || inputs.head_sha != '' || inputs.check_run_id != '')
+      uses: ./.github/workflows/validate-dispatch-inputs.yml
+      with:
+        pr: ${{ inputs.pr }}
+        head_sha: ${{ inputs.head_sha }}
+        check_run_id: ${{ inputs.check_run_id }}

     check-valgrind-suppressions:
       needs: [validate-dispatch-inputs]
diff --git a/.github/workflows/validate-dispatch-inputs.yml b/.github/workflows/validate-dispatch-inputs.yml
new file mode 100644
index 0000000000..a9e7f10ae4
--- /dev/null
+++ b/.github/workflows/validate-dispatch-inputs.yml
@@ -0,0 +1,37 @@
+# Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the LICENSE file in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+name: Validate CI bot dispatch inputs
+
+on:
+  workflow_call:
+    inputs:
+      pr:
+        required: true
+        type: string
+      head_sha:
+        required: true
+        type: string
+      check_run_id:
+        required: true
+        type: string
+
+permissions: {}
+
+jobs:
+  validate:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Validate pr / head_sha / check_run_id
+        env:
+          PR: ${{ inputs.pr }}
+          HEAD_SHA: ${{ inputs.head_sha }}
+          CHECK_RUN_ID: ${{ inputs.check_run_id }}
+        run: |
+          [[ "$PR" =~ ^[1-9][0-9]*$ ]] || { echo "::error::pr must be a positive integer"; exit 1; }
+          [[ "$CHECK_RUN_ID" =~ ^[1-9][0-9]*$ ]] || { echo "::error::check_run_id must be a positive integer"; exit 1; }
+          [[ "$HEAD_SHA" =~ ^[0-9a-f]{40}$ ]] || { echo "::error::head_sha must be a 40-character lowercase hex commit SHA"; exit 1; }