From 6ef0bc013b6aa5b23c5e4a9ee776b859b18d0d45 Mon Sep 17 00:00:00 2001 From: Ed Savage Date: Wed, 5 Aug 2026 10:29:08 +1200 Subject: [PATCH 1/2] [ML] Send version-bump Slack notification to #machine-learn-build and #ml-core Buildkite's slack notify accepts a list of channels; emit one YAML list item per channel and default to both #machine-learn-build and #ml-core. The ML_CPP_VERSION_BUMP_SLACK_CHANNEL override now takes a comma-separated list. Co-authored-by: Cursor --- .../send_slack_version_bump_notification.sh | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/.buildkite/pipelines/send_slack_version_bump_notification.sh b/.buildkite/pipelines/send_slack_version_bump_notification.sh index f12c8aa72..09f1b9311 100755 --- a/.buildkite/pipelines/send_slack_version_bump_notification.sh +++ b/.buildkite/pipelines/send_slack_version_bump_notification.sh @@ -17,7 +17,8 @@ # message would appear hours late or never if someone checks earlier. # # Optional env: -# ML_CPP_VERSION_BUMP_SLACK_CHANNEL — override channel (default #machine-learn-build) +# ML_CPP_VERSION_BUMP_SLACK_CHANNEL — override channel(s). Comma-separated list +# for multiple channels (default "#machine-learn-build,#ml-core"). set -euo pipefail @@ -26,7 +27,24 @@ REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" # shellcheck source=../../dev-tools/version_bump_lib.sh source "${REPO_ROOT}/dev-tools/version_bump_lib.sh" -CHANNEL="${ML_CPP_VERSION_BUMP_SLACK_CHANNEL:-#machine-learn-build}" +# Buildkite's slack notify accepts a list of channels, so a single build can fan +# the notification out to several. Accept a comma-separated override and render +# each entry as its own YAML list item (CHANNELS_YAML) injected into the notify +# block below. The Buildkite Slack app must be connected to every channel named +# here or the post is silently dropped for that channel. +CHANNELS_RAW="${ML_CPP_VERSION_BUMP_SLACK_CHANNEL:-#machine-learn-build,#ml-core}" +CHANNELS_YAML="" +IFS=',' read -ra _channels <<<"${CHANNELS_RAW}" +for _ch in "${_channels[@]}"; do + _ch="$(version_bump_trim_value "${_ch}")" + [[ -z "${_ch}" ]] && continue + CHANNELS_YAML+=" - \"${_ch}\""$'\n' +done +CHANNELS_YAML="${CHANNELS_YAML%$'\n'}" +if [[ -z "${CHANNELS_YAML}" ]]; then + echo "ERROR: no Slack channels resolved from ML_CPP_VERSION_BUMP_SLACK_CHANNEL='${CHANNELS_RAW}'." >&2 + exit 1 +fi if [[ "${BUILDKITE:-}" != "true" ]]; then echo "BUILDKITE is not true — skipping Slack notification (local run)." @@ -73,7 +91,7 @@ steps: notify: - slack: channels: - - "${CHANNEL}" +${CHANNELS_YAML} message: | ${slack_title} @@ -114,7 +132,7 @@ steps: notify: - slack: channels: - - "${CHANNEL}" +${CHANNELS_YAML} message: | ${slack_title} From 9cb1156c881cc674b34db24c7266634efd2fef4e Mon Sep 17 00:00:00 2001 From: Ed Savage Date: Wed, 5 Aug 2026 14:23:09 +1200 Subject: [PATCH 2/2] [ML] Address review: validate Slack channel entries before YAML interpolation Each ML_CPP_VERSION_BUMP_SLACK_CHANNEL entry is now checked against an allowlist of characters valid for a Slack notify target (#chan, @user, IDs, [token]#chan) and the build fails fast on anything else, so a malformed override cannot emit invalid pipeline YAML or inject steps. Co-authored-by: Cursor --- .../send_slack_version_bump_notification.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.buildkite/pipelines/send_slack_version_bump_notification.sh b/.buildkite/pipelines/send_slack_version_bump_notification.sh index 09f1b9311..f13ad91c6 100755 --- a/.buildkite/pipelines/send_slack_version_bump_notification.sh +++ b/.buildkite/pipelines/send_slack_version_bump_notification.sh @@ -34,10 +34,22 @@ source "${REPO_ROOT}/dev-tools/version_bump_lib.sh" # here or the post is silently dropped for that channel. CHANNELS_RAW="${ML_CPP_VERSION_BUMP_SLACK_CHANNEL:-#machine-learn-build,#ml-core}" CHANNELS_YAML="" +# Each entry is interpolated into the generated pipeline YAML inside double +# quotes, so restrict it to characters valid for a Slack notify target: #channel, +# @user, a channel/user ID, or Buildkite's [token]#channel form. Rejecting +# anything else (quotes, backslashes, newlines, spaces, ...) fails fast on a +# malformed override rather than emitting invalid YAML or allowing YAML/step +# injection. ']' is first and '-' last in the class so both are literal, and no +# backslash appears in the class so '\' is not accepted. +_channel_allowed='^[]A-Za-z0-9_.#@[-]+$' IFS=',' read -ra _channels <<<"${CHANNELS_RAW}" for _ch in "${_channels[@]}"; do _ch="$(version_bump_trim_value "${_ch}")" [[ -z "${_ch}" ]] && continue + if [[ ! "${_ch}" =~ $_channel_allowed ]]; then + echo "ERROR: invalid Slack channel '${_ch}' in ML_CPP_VERSION_BUMP_SLACK_CHANNEL; allowed characters: letters, digits and '# @ _ . - [ ]'." >&2 + exit 1 + fi CHANNELS_YAML+=" - \"${_ch}\""$'\n' done CHANNELS_YAML="${CHANNELS_YAML%$'\n'}"