
























@@ -59,7 +59,7 @@ on:
5959 - qa-parity
6060 - qa-live
6161live_suite_filter:
62-description: Optional exact live/E2E suite id, or comma-separated QA live lanes such as qa-live-matrix,qa-live-telegram; blank runs all selected live suites
62+description: Optional exact live/E2E suite id, or comma-separated QA live lanes such as qa-live-matrix,qa-live-telegram,qa-live-discord,qa-live-whatsapp; blank runs all selected live suites
6363required: false
6464default: ""
6565type: string
@@ -102,6 +102,8 @@ jobs:
102102cross_os_suite_filter: ${{ steps.inputs.outputs.cross_os_suite_filter }}
103103qa_live_matrix_enabled: ${{ steps.inputs.outputs.qa_live_matrix_enabled }}
104104qa_live_telegram_enabled: ${{ steps.inputs.outputs.qa_live_telegram_enabled }}
105+qa_live_discord_enabled: ${{ steps.inputs.outputs.qa_live_discord_enabled }}
106+qa_live_whatsapp_enabled: ${{ steps.inputs.outputs.qa_live_whatsapp_enabled }}
105107qa_live_slack_enabled: ${{ steps.inputs.outputs.qa_live_slack_enabled }}
106108package_acceptance_package_spec: ${{ steps.inputs.outputs.package_acceptance_package_spec }}
107109steps:
@@ -222,19 +224,35 @@ jobs:
222224RELEASE_RERUN_GROUP_INPUT: ${{ inputs.rerun_group }}
223225RELEASE_LIVE_SUITE_FILTER_INPUT: ${{ inputs.live_suite_filter }}
224226RELEASE_CROSS_OS_SUITE_FILTER_INPUT: ${{ inputs.cross_os_suite_filter }}
225-RELEASE_QA_SLACK_LIVE_CI_ENABLED: ${{ vars.OPENCLAW_QA_SLACK_LIVE_CI_ENABLED || 'false' }}
227+RELEASE_QA_DISCORD_LIVE_CI_ENABLED: ${{ vars.OPENCLAW_RELEASE_QA_DISCORD_LIVE_CI_ENABLED || 'false' }}
228+RELEASE_QA_WHATSAPP_LIVE_CI_ENABLED: ${{ vars.OPENCLAW_RELEASE_QA_WHATSAPP_LIVE_CI_ENABLED || 'false' }}
229+RELEASE_QA_SLACK_LIVE_CI_ENABLED: ${{ vars.OPENCLAW_RELEASE_QA_SLACK_LIVE_CI_ENABLED || 'false' }}
226230RELEASE_PACKAGE_ACCEPTANCE_PACKAGE_SPEC_INPUT: ${{ inputs.package_acceptance_package_spec }}
227231run: |
228232 set -euo pipefail
229233 qa_live_matrix_enabled=true
230234 qa_live_telegram_enabled=true
231- qa_live_slack_enabled=false
235+ qa_live_discord_ci_enabled="$(printf '%s' "$RELEASE_QA_DISCORD_LIVE_CI_ENABLED" | tr '[:upper:]' '[:lower:]')"
236+ if [[ "$qa_live_discord_ci_enabled" != "true" && "$qa_live_discord_ci_enabled" != "1" && "$qa_live_discord_ci_enabled" != "yes" ]]; then
237+ qa_live_discord_ci_enabled=false
238+ else
239+ qa_live_discord_ci_enabled=true
240+ fi
241+ qa_live_whatsapp_ci_enabled="$(printf '%s' "$RELEASE_QA_WHATSAPP_LIVE_CI_ENABLED" | tr '[:upper:]' '[:lower:]')"
242+ if [[ "$qa_live_whatsapp_ci_enabled" != "true" && "$qa_live_whatsapp_ci_enabled" != "1" && "$qa_live_whatsapp_ci_enabled" != "yes" ]]; then
243+ qa_live_whatsapp_ci_enabled=false
244+ else
245+ qa_live_whatsapp_ci_enabled=true
246+ fi
232247 qa_live_slack_ci_enabled="$(printf '%s' "$RELEASE_QA_SLACK_LIVE_CI_ENABLED" | tr '[:upper:]' '[:lower:]')"
233248 if [[ "$qa_live_slack_ci_enabled" != "true" && "$qa_live_slack_ci_enabled" != "1" && "$qa_live_slack_ci_enabled" != "yes" ]]; then
234249 qa_live_slack_ci_enabled=false
235250 else
236251 qa_live_slack_ci_enabled=true
237252 fi
253+ qa_live_discord_enabled="$qa_live_discord_ci_enabled"
254+ qa_live_whatsapp_enabled="$qa_live_whatsapp_ci_enabled"
255+ qa_live_slack_enabled="$qa_live_slack_ci_enabled"
238256 run_release_soak="$(printf '%s' "$RELEASE_RUN_RELEASE_SOAK_INPUT" | tr '[:upper:]' '[:lower:]')"
239257 if [[ "$run_release_soak" != "true" && "$run_release_soak" != "1" && "$run_release_soak" != "yes" ]]; then
240258 run_release_soak=false
@@ -250,6 +268,8 @@ jobs:
250268 qa_filter_seen=false
251269 matrix_selected=false
252270 telegram_selected=false
271+ discord_selected=false
272+ whatsapp_selected=false
253273 slack_selected=false
254274255275 IFS=', ' read -r -a filter_tokens <<< "$filter"
@@ -263,11 +283,16 @@ jobs:
263283 qa_filter_seen=true
264284 matrix_selected=true
265285 telegram_selected=true
286+ discord_selected="$qa_live_discord_ci_enabled"
287+ whatsapp_selected="$qa_live_whatsapp_ci_enabled"
288+ slack_selected="$qa_live_slack_ci_enabled"
266289 ;;
267290 qa-live-non-slack|qa-non-slack|non-slack|no-slack|without-slack)
268291 qa_filter_seen=true
269292 matrix_selected=true
270293 telegram_selected=true
294+ discord_selected="$qa_live_discord_ci_enabled"
295+ whatsapp_selected="$qa_live_whatsapp_ci_enabled"
271296 ;;
272297 qa-live-matrix|qa-matrix|matrix)
273298 qa_filter_seen=true
@@ -277,6 +302,14 @@ jobs:
277302 qa_filter_seen=true
278303 telegram_selected=true
279304 ;;
305+ qa-live-discord|qa-discord|discord)
306+ qa_filter_seen=true
307+ discord_selected="$qa_live_discord_ci_enabled"
308+ ;;
309+ qa-live-whatsapp|qa-whatsapp|whatsapp)
310+ qa_filter_seen=true
311+ whatsapp_selected="$qa_live_whatsapp_ci_enabled"
312+ ;;
280313 qa-live-slack|qa-slack|slack)
281314 qa_filter_seen=true
282315 slack_selected="$qa_live_slack_ci_enabled"
@@ -287,6 +320,8 @@ jobs:
287320 if [[ "$qa_filter_seen" == "true" ]]; then
288321 qa_live_matrix_enabled="$matrix_selected"
289322 qa_live_telegram_enabled="$telegram_selected"
323+ qa_live_discord_enabled="$discord_selected"
324+ qa_live_whatsapp_enabled="$whatsapp_selected"
290325 qa_live_slack_enabled="$slack_selected"
291326 fi
292327 fi
@@ -302,6 +337,8 @@ jobs:
302337 printf 'cross_os_suite_filter=%s\n' "$RELEASE_CROSS_OS_SUITE_FILTER_INPUT"
303338 printf 'qa_live_matrix_enabled=%s\n' "$qa_live_matrix_enabled"
304339 printf 'qa_live_telegram_enabled=%s\n' "$qa_live_telegram_enabled"
340+ printf 'qa_live_discord_enabled=%s\n' "$qa_live_discord_enabled"
341+ printf 'qa_live_whatsapp_enabled=%s\n' "$qa_live_whatsapp_enabled"
305342 printf 'qa_live_slack_enabled=%s\n' "$qa_live_slack_enabled"
306343 printf 'package_acceptance_package_spec=%s\n' "$RELEASE_PACKAGE_ACCEPTANCE_PACKAGE_SPEC_INPUT"
307344 } >> "$GITHUB_OUTPUT"
@@ -337,7 +374,7 @@ jobs:
337374 if [[ -n "${RELEASE_CROSS_OS_SUITE_FILTER// }" ]]; then
338375 echo "- Cross-OS suite filter: \`${RELEASE_CROSS_OS_SUITE_FILTER}\`"
339376 fi
340- echo "- QA live lanes: Matrix \`${{ steps.inputs.outputs.qa_live_matrix_enabled }}\`, Telegram \`${{ steps.inputs.outputs.qa_live_telegram_enabled }}\`, Slack \`${{ steps.inputs.outputs.qa_live_slack_enabled }}\`"
377+ echo "- QA live lanes: Matrix \`${{ steps.inputs.outputs.qa_live_matrix_enabled }}\`, Telegram \`${{ steps.inputs.outputs.qa_live_telegram_enabled }}\`, Discord \`${{ steps.inputs.outputs.qa_live_discord_enabled }}\`, WhatsApp \`${{ steps.inputs.outputs.qa_live_whatsapp_enabled }}\`, Slack \`${{ steps.inputs.outputs.qa_live_slack_enabled }}\`"
341378 if [[ -n "${PACKAGE_ACCEPTANCE_PACKAGE_SPEC// }" ]]; then
342379 echo "- Package Acceptance package spec: \`${PACKAGE_ACCEPTANCE_PACKAGE_SPEC}\`"
343380 else
@@ -926,10 +963,198 @@ jobs:
926963retention-days: 14
927964if-no-files-found: warn
928965966+qa_live_discord_release_checks:
967+name: Run QA Lab live Discord lane
968+needs: [resolve_target]
969+if: contains(fromJSON('["all","qa","qa-live"]'), needs.resolve_target.outputs.rerun_group) && needs.resolve_target.outputs.qa_live_discord_enabled == 'true' && vars.OPENCLAW_RELEASE_QA_DISCORD_LIVE_CI_ENABLED == 'true'
970+continue-on-error: true
971+runs-on: blacksmith-8vcpu-ubuntu-2404
972+timeout-minutes: 60
973+permissions:
974+contents: read
975+pull-requests: read
976+environment: qa-live-shared
977+env:
978+OPENCLAW_BUILD_PRIVATE_QA: "1"
979+OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
980+steps:
981+ - name: Checkout selected ref
982+uses: actions/checkout@v6
983+with:
984+persist-credentials: false
985+ref: ${{ needs.resolve_target.outputs.revision }}
986+fetch-depth: 1
987+988+ - name: Setup Node environment
989+uses: ./.github/actions/setup-node-env
990+with:
991+node-version: ${{ env.NODE_VERSION }}
992+pnpm-version: ${{ env.PNPM_VERSION }}
993+install-bun: "true"
994+995+ - name: Validate required QA credential env
996+env:
997+OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
998+OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
999+shell: bash
1000+run: |
1001+ set -euo pipefail
1002+1003+ require_var() {
1004+ local key="$1"
1005+ if [[ -z "${!key:-}" ]]; then
1006+ echo "Missing required ${key}." >&2
1007+ exit 1
1008+ fi
1009+ }
1010+1011+ require_var OPENCLAW_QA_CONVEX_SITE_URL
1012+ require_var OPENCLAW_QA_CONVEX_SECRET_CI
1013+1014+ - name: Build private QA runtime
1015+run: pnpm build
1016+1017+ - name: Run Discord live lane
1018+id: run_lane
1019+shell: bash
1020+env:
1021+OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
1022+OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
1023+OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
1024+OPENCLAW_QA_DISCORD_CAPTURE_CONTENT: "1"
1025+run: |
1026+ set -euo pipefail
1027+1028+ output_dir=".artifacts/qa-e2e/discord-live-release-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
1029+ echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
1030+1031+ for attempt in 1 2; do
1032+ attempt_output_dir="${output_dir}/attempt-${attempt}"
1033+ if pnpm openclaw qa discord \
1034+ --repo-root . \
1035+ --output-dir "${attempt_output_dir}" \
1036+ --provider-mode mock-openai \
1037+ --model mock-openai/gpt-5.5 \
1038+ --alt-model mock-openai/gpt-5.5-alt \
1039+ --fast \
1040+ --credential-source convex \
1041+ --credential-role ci; then
1042+ exit 0
1043+ fi
1044+ if [[ "${attempt}" == "2" ]]; then
1045+ exit 1
1046+ fi
1047+ echo "Discord live lane failed on attempt ${attempt}; retrying once..." >&2
1048+ sleep 10
1049+ done
1050+1051+ - name: Upload Discord QA artifacts
1052+if: always()
1053+uses: actions/upload-artifact@v4
1054+with:
1055+name: release-qa-live-discord-${{ needs.resolve_target.outputs.revision }}
1056+path: .artifacts/qa-e2e/
1057+retention-days: 14
1058+if-no-files-found: warn
1059+1060+qa_live_whatsapp_release_checks:
1061+name: Run QA Lab live WhatsApp lane
1062+needs: [resolve_target]
1063+if: contains(fromJSON('["all","qa","qa-live"]'), needs.resolve_target.outputs.rerun_group) && needs.resolve_target.outputs.qa_live_whatsapp_enabled == 'true' && vars.OPENCLAW_RELEASE_QA_WHATSAPP_LIVE_CI_ENABLED == 'true'
1064+continue-on-error: true
1065+runs-on: blacksmith-8vcpu-ubuntu-2404
1066+timeout-minutes: 60
1067+permissions:
1068+contents: read
1069+pull-requests: read
1070+environment: qa-live-shared
1071+env:
1072+OPENCLAW_BUILD_PRIVATE_QA: "1"
1073+OPENCLAW_ENABLE_PRIVATE_QA_CLI: "1"
1074+steps:
1075+ - name: Checkout selected ref
1076+uses: actions/checkout@v6
1077+with:
1078+persist-credentials: false
1079+ref: ${{ needs.resolve_target.outputs.revision }}
1080+fetch-depth: 1
1081+1082+ - name: Setup Node environment
1083+uses: ./.github/actions/setup-node-env
1084+with:
1085+node-version: ${{ env.NODE_VERSION }}
1086+pnpm-version: ${{ env.PNPM_VERSION }}
1087+install-bun: "true"
1088+1089+ - name: Validate required QA credential env
1090+env:
1091+OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
1092+OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
1093+shell: bash
1094+run: |
1095+ set -euo pipefail
1096+1097+ require_var() {
1098+ local key="$1"
1099+ if [[ -z "${!key:-}" ]]; then
1100+ echo "Missing required ${key}." >&2
1101+ exit 1
1102+ fi
1103+ }
1104+1105+ require_var OPENCLAW_QA_CONVEX_SITE_URL
1106+ require_var OPENCLAW_QA_CONVEX_SECRET_CI
1107+1108+ - name: Build private QA runtime
1109+run: pnpm build
1110+1111+ - name: Run WhatsApp live lane
1112+id: run_lane
1113+shell: bash
1114+env:
1115+OPENCLAW_QA_CONVEX_SITE_URL: ${{ secrets.OPENCLAW_QA_CONVEX_SITE_URL }}
1116+OPENCLAW_QA_CONVEX_SECRET_CI: ${{ secrets.OPENCLAW_QA_CONVEX_SECRET_CI }}
1117+OPENCLAW_QA_REDACT_PUBLIC_METADATA: "1"
1118+OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT: "1"
1119+run: |
1120+ set -euo pipefail
1121+1122+ output_dir=".artifacts/qa-e2e/whatsapp-live-release-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
1123+ echo "output_dir=${output_dir}" >> "$GITHUB_OUTPUT"
1124+1125+ for attempt in 1 2; do
1126+ attempt_output_dir="${output_dir}/attempt-${attempt}"
1127+ if pnpm openclaw qa whatsapp \
1128+ --repo-root . \
1129+ --output-dir "${attempt_output_dir}" \
1130+ --provider-mode mock-openai \
1131+ --model mock-openai/gpt-5.5 \
1132+ --alt-model mock-openai/gpt-5.5-alt \
1133+ --fast \
1134+ --credential-source convex \
1135+ --credential-role ci; then
1136+ exit 0
1137+ fi
1138+ if [[ "${attempt}" == "2" ]]; then
1139+ exit 1
1140+ fi
1141+ echo "WhatsApp live lane failed on attempt ${attempt}; retrying once..." >&2
1142+ sleep 10
1143+ done
1144+1145+ - name: Upload WhatsApp QA artifacts
1146+if: always()
1147+uses: actions/upload-artifact@v4
1148+with:
1149+name: release-qa-live-whatsapp-${{ needs.resolve_target.outputs.revision }}
1150+path: .artifacts/qa-e2e/
1151+retention-days: 14
1152+if-no-files-found: warn
1153+9291154qa_live_slack_release_checks:
9301155name: Run QA Lab live Slack lane
9311156needs: [resolve_target]
932-if: contains(fromJSON('["all","qa","qa-live"]'), needs.resolve_target.outputs.rerun_group) && needs.resolve_target.outputs.qa_live_slack_enabled == 'true' && vars.OPENCLAW_QA_SLACK_LIVE_CI_ENABLED == 'true'
1157+if: contains(fromJSON('["all","qa","qa-live"]'), needs.resolve_target.outputs.rerun_group) && needs.resolve_target.outputs.qa_live_slack_enabled == 'true' && vars.OPENCLAW_RELEASE_QA_SLACK_LIVE_CI_ENABLED == 'true'
9331158continue-on-error: true
9341159runs-on: blacksmith-8vcpu-ubuntu-2404
9351160timeout-minutes: 60
@@ -1033,6 +1258,8 @@ jobs:
10331258 - qa_lab_parity_report_release_checks
10341259 - qa_live_matrix_release_checks
10351260 - qa_live_telegram_release_checks
1261+ - qa_live_discord_release_checks
1262+ - qa_live_whatsapp_release_checks
10361263 - qa_live_slack_release_checks
10371264if: always()
10381265runs-on: ubuntu-24.04
@@ -1055,6 +1282,8 @@ jobs:
10551282 "qa_lab_parity_report_release_checks=${{ needs.qa_lab_parity_report_release_checks.result }}" \
10561283 "qa_live_matrix_release_checks=${{ needs.qa_live_matrix_release_checks.result }}" \
10571284 "qa_live_telegram_release_checks=${{ needs.qa_live_telegram_release_checks.result }}" \
1285+ "qa_live_discord_release_checks=${{ needs.qa_live_discord_release_checks.result }}" \
1286+ "qa_live_whatsapp_release_checks=${{ needs.qa_live_whatsapp_release_checks.result }}" \
10581287 "qa_live_slack_release_checks=${{ needs.qa_live_slack_release_checks.result }}"
10591288 do
10601289 name="${item%%=*}"
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。